package com.android.support.lib.universal.anim;

import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.annotation.SuppressLint;
import android.os.CountDownTimer;
import android.util.Log;
import android.view.View;

/**
 * 属性动画 ImageView img_rotating;//添加动画的控件，可以是任意控件 RotationAnim anim=new
 * RotationAnim(img_rotating);//动画默认是以自我为中心逆时针旋转
 * <p>
 * anim.startOrEnd();//开始,结束 anim.pauseOrResume();//暂停，继续
 * anim.isAnim;//当前是否正在进行动画 anim.updateListener.isPause();//当前动画是否处于暂停状态
 * <p>
 * anim.rotationAnim(控件, y * degree);//从当前角度，旋转到指定角度
 * <p>
 * 注意：不能在Thread子线程中，调用。会出错
 *
 * @author 彭治铭
 */
@SuppressLint("NewApi")
public class RotationAnim {
    ObjectAnimator animator;
    View view;
    /**
     * 当前是否正在进行动画
     */
    Boolean isAnim = false;
    MyAnimatorUpdateListener updateListener = new MyAnimatorUpdateListener();

    public RotationAnim() {
        super();
        // TODO Auto-generated constructor stub
    }

    /**
     * 只对Android3.0及以上有效 ,动画默认构造方法是以自我为中心逆时针旋转
     *
     * @param view 添加动画的控件
     */
    @SuppressLint("NewApi")
    public RotationAnim(View view) {
        super();
        this.view = view;
        /**
         * view 添加属性动画的控件 rotation 旋转动画效果（还有
         * x（移动x坐标,）,y（移动y坐标））,RotationY(立体旋转),RotationX(立体旋转) 0f 开始旋转的角度 -360f
         * 结束旋转的角度，正数顺时针，负数逆时针
         */
        animator = ObjectAnimator.ofFloat(view, "rotation", 0f, -360f);
        /**
         * 动画次数无限循环,0代表一次，1代表2次
         */
        animator.setRepeatCount(ValueAnimator.INFINITE);
        /**
         * 动画时间
         */
        animator.setDuration(1200);
        /**
         * 添加 暂停/继续 监听事件
         */
        animator.addUpdateListener(updateListener);
    }

    /**
     * 只对Android3.0及以上有效
     *
     * @param view         添加动画的控件
     * @param propertyName 可填rotation(中心旋转，一般就填写这个),x（移动x坐标,）,y（移动y坐标））,RotationY(立体旋转),
     *                     RotationX(立体旋转)
     * @param start        开始旋转的角度(一般填写 0f即可)
     * @param end          结束旋转的角度，正数顺时针，负数逆时针(一般填写 360f或 -360f)
     */
    @SuppressLint("NewApi")
    public RotationAnim(View view, String propertyName, float start, float end) {
        super();
        this.view = view;
        /**
         * view 添加属性动画的控件 rotation 旋转动画效果（还有
         * x（移动x坐标,）,y（移动y坐标））,RotationY(立体旋转),RotationX(立体旋转) 0f 开始旋转的角度 -360f
         * 结束旋转的角度，正数顺时针，负数逆时针
         */
        // animator = ObjectAnimator.ofFloat(view, "rotation", 0f, -360f);
        animator = ObjectAnimator.ofFloat(view, propertyName, start, end);
        /**
         * 动画次数无限循环,0代表一次，1代表2次
         */
        animator.setRepeatCount(ValueAnimator.INFINITE);
        /**
         * 动画时间
         */
        animator.setDuration(1200);
        /**
         * 添加 暂停/继续 监听事件
         */
        animator.addUpdateListener(updateListener);
    }

    /**
     * 从当前角度，旋转到指定角度.针对动画属性为"rotation"。
     *
     * @param view 控件
     * @param end  结束角度
     */
    public void rotationAnim(View view, float end) {

        // 获取当前旋转角度
        float start = 0f;
        try {
            if (animator.getAnimatedValue("rotation") != null) {
                start = (Float) animator.getAnimatedValue("rotation");
            }
        } catch (Exception e) {
            // TODO: handle exception
            Log.e("動畫空值錯誤", "動畫空值錯誤");
        }

        this.view = view;
        /**
         * view 添加属性动画的控件 rotation 旋转动画效果（还有 x（移动x坐标）,y（移动y坐标）） 0f 开始旋转的角度 -360f
         * 结束旋转的角度，正数顺时针，负数逆时针
         */
        animator = ObjectAnimator.ofFloat(view, "rotation", start, -end);
        /**
         * 动画次数无限循环,0代表一次，1代表2次
         */
        animator.setRepeatCount(0);
        /**
         * 动画时间,1000代表一秒
         */
        animator.setDuration(0);
        /**
         * 添加 暂停/继续 监听事件
         */
        animator.addUpdateListener(updateListener);
        animator.start();
    }

    /**
     * 开始动画 /结束动画
     */
    public void startOrEnd() {
        if (!isAnim) {
            animator.start();
        } else {
            updateListener.play();
            animator.end();
        }
        isAnim = !isAnim;
    }

    /**
     * 暂停动画/继续动画
     */
    public void pauseOrResume() {
        if (isAnim) {
            if (updateListener.isPause) {
                updateListener.play();
            } else {
                updateListener.pause();
            }
        }

    }

    @SuppressLint("NewApi")
    class MyAnimatorUpdateListener implements AnimatorUpdateListener {

        /**
         * 暂停状态
         */
        private boolean isPause = false;
        /**
         * 是否已经暂停，如果一已经暂停，那么就不需要再次设置停止的一些事件和监听器了
         */
        private boolean isPaused = false;
        /**
         * 当前的动画的播放位置
         */
        private float fraction = 0.0f;
        /**
         * 当前动画的播放运行时间
         */
        private long mCurrentPlayTime = 0l;

        /**
         * 是否是暂停状态
         *
         * @return
         */
        public boolean isPause() {
            return isPause;
        }

        /**
         * 停止方法，只是设置标志位，剩余的工作会根据状态位置在onAnimationUpdate进行操作
         */
        public void pause() {
            isPause = true;
        }

        public void play() {
            isPause = false;
            isPaused = false;
        }

        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            /**
             * 如果是暂停则将状态保持下来，并每个刷新动画的时间了；来设置当前时间，让动画
             * 在时间上处于暂停状态，同时要设置一个静止的时间加速器，来保证动画不会抖动
             */

            // animation.getAnimatedValue

            if (isPause) {
                if (!isPaused) {
                    //暂停位置
                    fraction = animation.getAnimatedFraction();
                    animation.setInterpolator(new TimeInterpolator() {
                        @Override
                        public float getInterpolation(float input) {
                            return fraction;
                        }
                    });
                    isPaused = true;
                    mCurrentPlayTime = animation.getCurrentPlayTime();
                }
                // 每隔动画播放的时间，我们都会将播放时间往回调整，以便重新播放的时候接着使用这个时间,同时也为了让整个动画不结束
                //倒计时定时器，暂停时间
                new CountDownTimer(ValueAnimator.getFrameDelay(),
                        ValueAnimator.getFrameDelay()) {

                    @Override
                    public void onTick(long millisUntilFinished) {
                    }

                    @Override
                    public void onFinish() {
                        animator.setCurrentPlayTime(mCurrentPlayTime);
                    }
                }.start();

            } else {
                // 将时间拦截器恢复成线性的，如果您有自己的，也可以在这里进行恢复
                animation.setInterpolator(null);
            }
        }

    }

}
